package process

import (
	"chatroom/client/utils"
	"chatroom/common/message"
	"encoding/binary"
	"encoding/json"
	"fmt"
	"net"
	_ "os"
)

type UserProcess struct {
	//暂时不需要字段...

}

//注册
func (up *UserProcess) Register(userId int,
	userPwd string, userName string) (err error) {

	//1. 连接到服务器端
	conn, err := net.Dial("tcp", "localhost:8889")
	if err != nil {
		fmt.Println("net.Dial err=", err)
		return
	}

	//延时关闭
	defer conn.Close()

	//2.准备通过conn发送消息给服务器
	var mes message.Message
	mes.Type = message.RegisterMesType
	//3.创建一个LoginMes 结构体
	var registerMes message.RegisterMes
	registerMes.User.UserId = userId
	registerMes.User.UserPwd = userPwd
	registerMes.User.UserName = userName

	//将register 进行序列化
	data, err := json.Marshal(registerMes)
	if err != nil {
		fmt.Println("loginMes json.Marshal err=", err)
		return
	}

	//5.把data 赋给 mes.Data字段
	mes.Data = string(data) //[]byte 转string

	//6.将 mes 进行序列化
	data, err = json.Marshal(mes)
	if err != nil {
		fmt.Println("mes json.Marshal err=", err)
		return
	}

	//fmt.Printf("客户端发送注册消息的长度=%d 内容是=%s", len(data), string(data))

	//这里还需要处理服务器端返回的消息
	//创建一个 Transfer 实例
	tf := &utils.TransFer{
		Conn: conn,
	}

	//发送 data 给服务器端
	err = tf.WritePkg(data)
	if err != nil {
		fmt.Println("注册发送消息错误 err=", err)
		return
	}

	//mes 就是 resgisterresmes
	mes, err = tf.ReadPkg() 
	if err != nil {
		fmt.Println("readPkg err=", err)
		return
	}

	//将 mes 的Data 部分反序列化成 RegisterResMes
	var registerResMes message.RegisterResMes
	err = json.Unmarshal([]byte(mes.Data), &registerResMes)
	if registerResMes.Code == 200 {
		fmt.Println("注册成功，重新登录..")
		//os.Exit(0)
	} else {
		fmt.Println(registerResMes.Error)
		//os.Exit(0)
	}
	
	return
}

//关联一个用户登录的方法
//写一个函数，完成一个登录
func (up *UserProcess) Login(userId int, userPwd string) (err error) {

	//下一步就要开始定协议..
	//fmt.Printf("userId = %d  userPwd= %s\n",userId, userPwd)
	//return nil

	//1. 连接到服务器端
	conn, err := net.Dial("tcp", "localhost:8889")
	if err != nil {
		fmt.Println("net.Dial err=", err)
		return
	}

	//延时关闭
	defer conn.Close()

	//2.准备通过conn发送消息给服务器
	var mes message.Message
	mes.Type = message.LoginMesType
	//3.创建一个LoginMes 结构体
	var loginMes message.LoginMes
	loginMes.UserId = userId
	loginMes.UserPwd = userPwd

	//4.将loginMes序列化
	data, err := json.Marshal(loginMes)
	if err != nil {
		fmt.Println("loginMes json.Marshal err=", err)
		return
	}

	//5.把data 赋给 mes.Data字段
	mes.Data = string(data) //[]byte 转string

	//6.将 mes 进行序列化
	data, err = json.Marshal(mes)
	if err != nil {
		fmt.Println("mes json.Marshal err=", err)
		return
	}

	//7.到这个时候，data就是我们要发送的数据
	//7.1先把 data 长度发送给服务器
	//先获取到 data 的长度 -> 转成一个切片
	var pkgLen uint32 = uint32(len(data))
	//因为 uint 是 4 个字节， 所以此处是[4]byte
	var buf [4]byte
	binary.BigEndian.PutUint32(buf[0:4], pkgLen)
	//发送长度
	n, err := conn.Write(buf[:4])
	if n != 4 || err != nil {
		fmt.Println("conn.Write json.Marshal err=", err)
		return
	}

	fmt.Printf("客户端发送消息的长度=%d 内容是=%s", len(data), string(data))

	//发送消息本身
	_, err = conn.Write(data)
	if err != nil {
		fmt.Println("conn.Write(data) err=", err)
		return
	}

	//这里还需要处理服务器端返回的消息
	//创建一个 Transfer 实例
	tf := &utils.TransFer{
		Conn: conn,
	}
	mes, err = tf.ReadPkg() //mes 就是
	if err != nil {
		fmt.Println("Login readPkg err=", err)
		return
	}
	//将 mes 的Data 部分反序列化成 LoginResMes
	var loginResMes message.LoginResMes
	err = json.Unmarshal([]byte(mes.Data), &loginResMes)
	if loginResMes.Code == 200 {
		//初始化curuser
		CurUser.Conn = conn
		CurUser.UserId = userId
		CurUser.UserStatus = message.UserOnline

		//fmt.Println("登录成功...")

		//现在可以显示当前在线用户列表，遍历 loginResMes.UsersId
		fmt.Println("\n当前在线用户列表如下：")
		for _, v := range loginResMes.UsersId {
			if v == userId {
				continue
			}
			fmt.Println("用户id:\t",v)
			//完成 客户端 onlineUsers 完成初始化
			user := &message.User{
				UserId : v,
				UserStatus : message.UserOnline,
			}
			onlineUsers[v] = user
		}
		fmt.Print("\n\n")

		//这里我们还需要在客户端启动一个协程
		//该协程保持和服务器端的通讯，如果服务器有数据推送给客户端
		//则接收并显示在客户端的终端
		go serverProcessMes(conn)

		//1.显示登录成功的菜单[循环显示]
		for {
			ShowMenu(userId)
		}
	} else {
		fmt.Println(loginResMes.Error)
	}

	return
}
